﻿using System;
using System.Windows.Forms;
using System.Diagnostics;
using System.IO;
using System.Text.RegularExpressions;
using System.Text;
using System.Linq;
using System.Collections.Generic;
using System.Drawing;
using System.Threading;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.TaskbarClock;
using System.Globalization;
using System.Management;
using System.Net.Http.Headers;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;
using System.Net;
using System.Runtime.InteropServices.ComTypes;
using System.Collections.Specialized;
using System.Security.Policy;
using FuzzyString;
using System.Net.NetworkInformation;
using CallSignAnalysis.Utils;
using System.Xml;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.StartPanel;
using Sunny.UI.Win32;
using Sunny.UI;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.Rebar;
using System.Runtime.Remoting.Metadata.W3cXsd2001;
using System.Xml.Linq;
using static System.Net.Mime.MediaTypeNames;
using Pinyin4net.Format;
using Pinyin4net;

namespace CallSignAnalysis
{
    public partial class Form1 : Form
    {
        //private string apiKey = "1cdff8602e4d62aac55ed6f4c8d6f3d8.KC9RcGm7YNOIrgTH";
        private List<QSOData> QsoList; // 全局QSO信息

        private string CONFIRM_EQSL_URL = "https://www.eQSL.cc/qslcard/ImportADIF.cfm";
        private bool LANG_INIT_STATUS = false; // 初始化完成后才能开始重启

        public Form1()
        {
            InitializeComponent();
            this.StartPosition = FormStartPosition.CenterScreen;

            this.FormBorderStyle = FormBorderStyle.FixedDialog;

            // 多语言
            InitGlobalLang();
        }

        /// <summary>
        /// QSO信息结构体
        /// </summary>
        public struct QSOData
        {
            public string freq;
            public string qsotime;
            public string satelitename;
            public string qsoCallsigns;
            public string mode;
            public string band;
            public string comment;

            public void DisplayInfo()
            {
                Console.WriteLine($"Frequency: {freq}");
                Console.WriteLine($"QSO Time: {qsotime}");
                Console.WriteLine($"Satellite Name: {satelitename}");
                Console.WriteLine($"QSO Callsign: {qsoCallsigns}");
                Console.WriteLine($"mode: {mode}");
            }
            public string GetInfo()
            {
                StringBuilder sb = new StringBuilder();

                if (satelitename != null)
                {
                    sb.AppendLine($"[{satelitename}]");
                }

                if (freq != null)
                {
                    sb.AppendLine($"Freq: {freq}");
                }

                if (qsotime != null)
                {
                    sb.AppendLine($"Time: {qsotime}");
                }

                if (qsoCallsigns != null)
                {
                    sb.AppendLine($"Work: {qsoCallsigns}");
                }

                if (mode != null)
                {
                    sb.AppendLine($"Mode: {mode}");
                }

                if (band != null)
                {
                    sb.AppendLine($"Band: {band}");
                }

                if (comment != null)
                {
                    sb.AppendLine($"Comment: {comment}");
                }

                // 如果你想要在没有任何值的情况下返回一个空字符串而不是一个空行，可以像这样添加一个检查：
                if (sb.Length == 0)
                {
                    return ""; // 或者任何其他你想要返回的默认值
                }

                // 如果有至少一个值不为 null，则会执行到这里
                return sb.ToString();
            }
        }

        private string LangReplace(string origin,string simple)
        {
            if (g.lang != "简体中文")
            {
                RWini.SetPath(g.lang + ".ini");
                origin = RWini.ReadValue("simple", simple);

            }
            return origin;
        }

        /// <summary>
        /// 初始化全球语言
        /// </summary>
        private void InitGlobalLang()
        {
            RWini.SetPath("config.ini");
            g.lang = RWini.ReadValue("lang", "current");

            if (g.lang != "")
            {
                combox_lang.SelectedIndex = combox_lang.Items.IndexOf(g.lang);
                if (combox_lang.SelectedIndex != 0)
                {
                    Sunny.UI.UILocalizeHelper.SetEN();
                }
            }
            else
            {
                combox_lang.SelectedIndex = 0;
                g.lang = "简体中文";
            }

            LANG_INIT_STATUS = true;

            RWini.SetPath(g.lang + ".ini");
            getControlFromName(this);
        }

        /// <summary>
        /// 递归方法,获取指定controlName的控件;如果控件未找到,则返回null,请注意判断null
        /// </summary>
        /// <param name="container">容器控件,可以是窗体form,也可以是panel,GroupBox等</param>
        /// <param name="controlName">控件名称</param>
        /// <returns>返回一个控件类型</returns>
        private Control getControlFromName(Control container)
        {
            foreach (Control c in container.Controls)
            {
                if (c is Sunny.UI.UIButton || c is Sunny.UI.UICheckBox || c is Sunny.UI.UILabel || c is Sunny.UI.UIGroupBox)
                {
                    string t = RWini.ReadValue(c.Name, "Text");
                    if (!string.IsNullOrWhiteSpace(t))
                    {
                        c.Text = t;
                        string name = RWini.ReadValue(c.Name, "Font");
                        int size = RWini.ReadInt(c.Name, "Size", 16);
                        string Sizes = RWini.ReadValue(c.Name, "Size");
                        int.TryParse(Sizes, out size);
                        if (!string.IsNullOrWhiteSpace(name))
                        {
                            FontFamily ff = new FontFamily(name);
                            FontStyle style = FontStyle.Bold;
                            // style |= FontStyle.Regular;
                            // style |= FontStyle.Italic;, GraphicsUnit.World
                            c.Font = new Font(ff, size, style);
                        }

                    }
                }
                if (c.HasChildren)
                {
                    //这里不能直接写return  getControlFromName(c, controlName);因为会导致只执行第一个子容器控件,如果未找到就提前返回了Null;
                    Control myControl = getControlFromName(c);
                    if (myControl != null)
                    {
                        return myControl;
                    }
                }
            }
            //并非所有的代码路径都返回值,未找到就返回null
            return null;
        }



        /// <summary>
        /// 检查匹配
        /// </summary>
        /// <param name="input"></param>
        /// <param name="options"></param>
        /// <returns></returns>
        static bool CheckMatch(string input, string[] options)
        {
            foreach (string option in options)
            {
                if (input.Contains(option))
                {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 解析短波的ADIF
        /// </summary>
        /// <returns></returns>
        private QSOData GenerateHFAdif(string input)
        {

            // 初始化变量
            string timePart = null;
            string freq = null;
            string band = null;
            string mode = null;
            string comment = null;
            List<string> callSignsList = new List<string>();

            input = input.Trim();

            // 使用空格分割字符串
            // string[] parts = input.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);


            // 匹配尖括号中的内容或非空格字符 然后匹配输入字符串
            string[] parts = Regex.Matches(input, @"<[^>]*>|[^\s]+").Cast<Match>().Select(e => e.Value).ToArray();

            // 逐个匹配
            foreach (string part in parts)
            {
                string partUpper = part.ToUpper().Trim(); // 统一大小写并去除前后空格

                string temp = part.Replace("：", ":");
                // 匹配时间部分
                if (timePart == null && System.Text.RegularExpressions.Regex.IsMatch(temp, @"(\d{1,2}:\d{2})|(\d{12})"))
                {
                    
                    timePart = ParseTime(temp); // 存储时间
                    if (CBox_Low8Hour.Checked)
                    {
                        timePart = AdjustDate(timePart, iud_timediff.Value);
                    }
                    continue;
                }

                // 匹配频率
                if (freq == null && Regex.IsMatch(part, @"\b\d{5,6}\b"))
                {
                    freq = part;
                    band = GetBand(float.Parse(freq));
                    continue;
                }

                // 匹配模式（FT8 CW SSB FM AM）
                string[] options = { "FT8", "CW", "SSB", "USB", "LSB", "FM", "AM", "PSK" };
                if (mode == null && CheckMatch(part.ToUpper(), options))
                {
                    mode = part.ToUpper();
                    continue;
                }



                //匹配comment（<> 包裹）
                if (comment == null && Regex.IsMatch(part, @"<([^<>]*)>"))
                {
                    comment = part.Replace('<',' ').Replace('>', ' ').Trim();
                    continue;
                }

                // 剩下的是呼号
                callSignsList.Add(part.ToUpper());
            }

            // 处理呼号
            string finalcallsigns = "";
            foreach (var callSign in callSignsList)
            {
                finalcallsigns += (callSign + " ");
            }

            QSOData qSOData = new QSOData
            {
                freq = freq,
                band = band,
                mode = mode,
                qsoCallsigns = finalcallsigns,
                qsotime = timePart,
                comment = comment
            };

            // 最后填充其他单元格
            box_qsoTime.Text = timePart;
            box_freq.Text = freq + " -> " + band;
            box_SateliteName.Text = "NOT SAT";

            return qSOData;
        }

        private string AdjustDate(string timeString, int adjustment)
        {
            // 定义要解析的时间格式
            string[] formats = { "yyyyMMdd HHmmss" };

            // 解析输入的时间字符串
            DateTime dateTime;
            bool success = DateTime.TryParseExact(timeString, formats, null, System.Globalization.DateTimeStyles.None, out dateTime);

            // 如果解析成功，则根据调整值调整日期
            if (success)
            {
                lab_qsoTime.ForeColor = Color.Black;
                DateTime adjustedDateTime = dateTime.AddHours(adjustment);
                // 返回调整后的日期时间字符串格式
                return adjustedDateTime.ToString("yyyyMMdd HHmmss");
            }
            else
            {
                lab_qsoTime.ForeColor = Color.Red;
                // 解析失败，可以返回错误信息或原始字符串
                return "TIME ERROR!";
            }
        }


        private QSOData GenerateAdif(string input)
        {
            string freq = ""; // 先设定一个变量freq 存储解析出来的频率
            

            // 使用空格分割字符串
            string[] parts = input.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

            // 初始化变量
            string timePart = null;
            string satelliteName = null;
            List<string> callSignsList = new List<string>();

            // 读取呼号排除项文件
            List<string> callsighlistFile = AddCallSignsFromFile("callsigns.ini");

            // 逐个匹配
            foreach (string part in parts)
            {
                string partUpper = part.ToUpper().Trim(); // 统一大小写并去除前后空格
                // 检查part是否在callsighlist中
                if (callsighlistFile.Contains(partUpper))
                {
                    Console.WriteLine($"{partUpper} 在排除列表中，将跳过处理。");
                    callSignsList.Add(partUpper);
                    continue; // 跳过当前循环迭代
                }

               
                string temp = part.Replace("：", ":");
                // 匹配时间部分
                if (Regex.IsMatch(temp, @"(^\d+$)|(\d{1,2}:\d{2})"))
                {
                    if (Regex.IsMatch(temp, @"(\d{1,2}:\d{1,2})") || temp.Length == 12)
                    {
                        timePart = ParseTime(temp);

                        if (CBox_Low8Hour.Checked)
                        {
                            timePart = AdjustDate(timePart, iud_timediff.Value);
                        }

                        lab_inputInfo.Text = LangReplace("空格隔开键入QSO信息", "lab_inputInfo");
                        lab_inputInfo.ForeColor = Color.Black;
                    }
                    else
                    {
                        // timeError
                        lab_inputInfo.Text = LangReplace("时间格式错误，请检查输入！", "timeError");
                        lab_inputInfo.ForeColor = Color.Red;
                    }
                }
                // 匹配卫星名称（部分匹配，不区分大小写）
                else
                {
                    

                    string bestMatch = FindBestMatch(part);

                    if (!string.IsNullOrEmpty(bestMatch) && satelliteName == null)
                    {
                        Console.WriteLine($"最佳匹配的卫星名称是: {bestMatch}");
                        satelliteName = bestMatch;

                        // 抽取别名
                        satelliteName = ReplaceSatName(satelliteName);

                        freq = getFreq(satelliteName);
                    }
                    else
                    {
                        Console.WriteLine("未找到匹配的卫星名称。");
                        // 添加呼号到列表
                        string callsign = part.ToUpper();
                        callSignsList.Add(callsign);

                    }

                }
                // 剩下的是呼号
            }

            // 输出结果
            tbox_outputBox.Text = ""; box_qsoTime.Text = ""; box_SateliteName.Text = "";
          //  timePart = CalcuTimeDiff(timePart); // 计算UTC

            box_freq.Text = freq;
            box_qsoTime.Text += (timePart);
            box_SateliteName.Text += (satelliteName);

            // 正则表达式 By BH8DKD
            string pattern = @"^([a-zA-Z0-9]{1,3}[\/]{1,1})?(([a-zA-Z0-9]{1,2}[0-9]{1,2})[a-zA-Z0-9]{0,3}[a-zA-Z])([\/]{1,1}[a-zA-Z0-9]{1,3})?$";
            string matched = "";

            // 呼号添加
            string finalcallsigns = "";
            foreach (var callSign in callSignsList)
            {
                finalcallsigns += (callSign + " ");

                Match match = Regex.Match(callSign, pattern);
                matched += (match.Value + " ");
            }

            // 展示数据
            // MessageBox.Show("匹配到的字符串：\n" + matched);
            
            QSOData qSOData = new QSOData
            {
                freq = freq,
                //qsotime = timePart,
                qsotime = box_qsoTime.Text,
                satelitename = satelliteName,
                //qsoCallsigns = finalcallsigns
                qsoCallsigns = matched
            };



            return qSOData;
        }

        /// <summary>
        /// 返回是否为数字
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        static bool IsDigit(string s)
        {
            int result;
            return int.TryParse(s, out result);
        }

        // 定义一个方法来从指定的文件路径读取呼号并添加到列表中
        List<string> AddCallSignsFromFile(string filePath)
        {
            // 假设callSignsList已经被定义为一个List<string>
            List<string> callSignsList = new List<string>();
            // 检查文件是否存在
            if (File.Exists(filePath))
            {
                // 读取所有行到一个字符串数组中
                string[] lines = File.ReadAllLines(filePath);

                // 遍历每一行（每个呼号）
                foreach (string line in lines)
                {
                    if (line.StartsWith("#") || string.IsNullOrWhiteSpace(line))
                    {
                        continue;
                    }
                    // 添加呼号到列表中
                    callSignsList.Add(line.Trim().ToUpper()); // 使用Trim()去除可能的前后空白，并转换为大写
                }
            }
            else
            {
                Console.WriteLine($"文件 {filePath} 不存在。");
            }

            return callSignsList;
        }

        private string ReplaceSatName(string sat)
        {
            if (sat == "GC")
            {
                sat = "IO-117";
            }

            if (sat == "HADES-D" || sat == "HDD")
            {
                sat = "SO-121";
            }

            if (sat == "HADES-R" || sat == "HDR")
            {
                sat = "SO-124";
            }
            
            if (sat == "AO-123" || sat == "ASRTU-1")
            {
                sat = "AO-123";
            }

            if (sat == "LILACSAT-2" || sat == "LILAC" || sat== "紫丁香2号" || sat== "紫2")
            {
                sat = "CAS-3H";
            }

            return sat;
        }

        static string ParseTime(string input)
        {
            string currentDate = DateTime.Now.ToString("yyyyMMdd");
            string currentTime = DateTime.Now.ToString("HHmm");

            string outputDate;
            string outputTime;

            if (input.Length == 12)
            {
                outputDate = input.Substring(0, 8);
                outputTime = input.Substring(8, 4);
                outputTime += "00";
            }
            else if (input.Contains(":"))
            {
                if (TimeSpan.TryParse(input, out TimeSpan timeSpan))
                {
                    // 使用ToString("HH:mm")格式化时间为两位数的小时和分钟
                    input = timeSpan.ToString("hh\\:mm");
                }
                outputDate = currentDate;
                outputTime = input.Replace(":", "");
                outputTime = outputTime.Replace("\n", "");
                if (outputTime.Length <= 4)
                {
                    outputTime = outputTime + "00";
                }
            }
            else if (input.Length == 4)
            {
                outputDate = currentDate;
                outputTime = input + "00";
            }
            else
            {
                Console.WriteLine("无法解析的输入格式");
                return null;
            }

            return outputDate + " " + outputTime;
        }

        private string getFreq(string satelliteName)
        {// 卫星频率映射
            Dictionary<string, string> SatelliteFrequencies = new Dictionary<string, string>
            {
                {"SO-50", "145.85↑ 436.795↓"},
                {"SO-121", "145.875↑ 436.666↓"},
                {"AO-27", "145.8↑ 436.795↓"},
                {"AO-91", "435.25↑ 145.96↓"},
                {"UVSQ", "145.905↑ 437.02↓"},
                {"PO-101", "437.5↑ 145.9↓"},
                {"CAS-3H", "144.35↑ 437.2↓"},
                {"ARISS", "145.99↑ 437.8↓"},
                {"INSPR7", "145.97↑ 437.41↓"},
                {"AO-92", "435.35↑ 145.88↓"},
                {"TEVEL1", "145.97↑ 436.4↓"},
                {"TEVEL2", "145.97↑ 436.4↓"},
                {"TEVEL3", "145.97↑ 436.4↓"},
                {"TEVEL4", "145.97↑ 436.4↓"},
                {"TEVEL5", "145.97↑ 436.4↓"},
                {"TEVEL6", "145.97↑ 436.4↓"},
                {"TEVEL7", "145.97↑ 436.4↓"},
                {"TEVEL8", "145.97↑ 436.4↓"},
                {"IO-117", "435.307↑ 435.31↓"},
                {"RS-44", "145.965↑ 435.6↓"},
                {"AO-123", "145.85↑ 435.4↓"},
                {"SO-124", "145.925↑ 436.88↓"},
                {"SO-125", "145.875↑ 436.666↓"},
            };


            string frequency;
            if (SatelliteFrequencies.TryGetValue(satelliteName, out frequency))
            {
                //Console.WriteLine($"{satelliteName} 的频率为 {frequency} MHz");
                return frequency;
            }
            else
            {
                //Console.WriteLine($"{satelliteName} 未找到，使用默认频率 145.0 MHz");
                return null;
            }
        }

        // 卫星名称列表
        static string[] SatelliteNames = {
        "SO-124","SO-50","SO-121", "AO-27", "AO-91", "AO-123","ASRTU-1", "UVSQ", "PO-101",
        "CAS-3H", "ARISS","INSPR7", "AO-92", "TEVEL1", "TEVEL2", "TEVEL3",
        "TEVEL4", "TEVEL5", "TEVEL6", "TEVEL7", "TEVEL8", "IO-117","GC","HADES-D","HADES-R","LILACSAT-2","紫丁香2号","紫2","LILAC","RS-44","SO-125"
        };
        public static string FindBestMatch(string input)
        {     
            
            // 正则表达式来匹配呼号
            string pattern = @"^([a-zA-Z0-9]{1,3}[\/]{1,1})?(([a-zA-Z0-9]{1,2}[0-9]{1,2})[a-zA-Z0-9]{0,3}[a-zA-Z])([\/]{1,1}[a-zA-Z0-9]{1,3})?$";
            Regex regex = new Regex(pattern);

            // 检查输入是否是呼号
            if (regex.IsMatch(input))
            {
                return "";
            }

            string bestMatch = "";
            double maxScore = 0.0;
            int bestOrderScore = int.MaxValue; // 初始化为最大值，以便第一个匹配项能够更新它

            foreach (string satelliteName in SatelliteNames)
            {
                double score = CalculateScore(input, satelliteName);
                int orderScore = CalculateOrderScore(input, satelliteName);

                // 更新最佳匹配，如果得分更高或者得分相同但顺序得分更好
                if (score > maxScore || (score == maxScore && orderScore < bestOrderScore))
                {
                    maxScore = score;
                    bestOrderScore = orderScore;
                    bestMatch = satelliteName;
                }
            }

            double threshold = 0.5;
            if (maxScore >= threshold)
            {
                return bestMatch;
            }
            else
            {
                return "";
            }
        }

        private static double CalculateScore(string input, string satelliteName)
        {
            string upperInput = input.ToUpper();
            string upperSatelliteName = satelliteName.ToUpper();
            int matches = upperInput.Intersect(upperSatelliteName).Count();
            return (double)matches / upperInput.Length;
        }

        private static int CalculateOrderScore(string input, string satelliteName)
        {
            string upperInput = input.ToUpper();
            string upperSatelliteName = satelliteName.ToUpper();
            int score = 0;
            int lastMatchIndex = -1;

            foreach (char c in upperInput)
            {
                int index = upperSatelliteName.IndexOf(c, lastMatchIndex + 1);
                if (index != -1)
                {
                    score += index - lastMatchIndex;
                    lastMatchIndex = index;
                }
                else
                {
                    // 如果字符在卫星名称中找不到，返回一个非常大的值，表示这不是一个好的匹配
                    return int.MaxValue;
                }
            }

            return score;
        }

        /// <summary>
        /// 中文转化成拼音
        /// </summary>
        /// <param name="chineseText">中文字符串</param>
        /// <returns>拼音字符串</returns>
        static string ConvertToPinyin(string chineseText)
        {
            string Capitalize(string text)
            {
                if (string.IsNullOrEmpty(text))
                    return text;

                return char.ToUpper(text[0]) + text.Substring(1).ToLower();
            }
            bool IsChinese(char c)
            {
                return Regex.IsMatch(c.ToString(), @"[\u4e00-\u9fa5]");
            }
            StringBuilder pinyinBuilder = new StringBuilder();
            var format = new HanyuPinyinOutputFormat
            {
                CaseType = HanyuPinyinCaseType.LOWERCASE,
                ToneType = HanyuPinyinToneType.WITHOUT_TONE,
                VCharType = HanyuPinyinVCharType.WITH_V
            };

            foreach (char c in chineseText)
            {
                if (IsChinese(c))
                {
                    // 获取汉字的拼音列表
                    string[] pinyins = PinyinHelper.ToHanyuPinyinStringArray(c, format);
                    if (pinyins != null && pinyins.Length > 0)
                    {
                        string pinyinForChar = pinyins[0];
                        // 首字母大写
                        pinyinForChar = Capitalize(pinyinForChar);
                        pinyinBuilder.Append(pinyinForChar + " ");
                    }
                }
                else
                {
                    // 如果不是中文字符，直接添加
                    pinyinBuilder.Append(c);
                }
            }

            return pinyinBuilder.ToString().Trim();
        }

       



        private void Btn_analysis_Click(object sender, EventArgs e)
        {
            if (tbox_inputbox.Text != "")
            {
                // QSO队列 
                string boxText = tbox_inputbox.Text;
                //Sunny.UI.UINotifierHelper.ShowNotifier(RWini.ReadValue("CNtoPinYin", "checked"), 0, "⭐SAT QSO", false, 1500, null);

                if (RWini.ReadValue("CNtoPinYin", "checked") == "true") {
                    boxText = ConvertToPinyin(boxText.Trim());
                }

                string[] satArr = boxText.Replace("\n", "").Replace("\r", "").Replace("\t", " ").Split('*');

                // 全局QSO清空重置
                QsoList = new List<QSOData>();
                tbox_outputBox.Text = "";

                string pattern = @"\b\d{5,6}\b"; // 匹配5位数字的单词边界
                for (int i = 0; i < satArr.Length; i++)
                {
                    //去空
                    if (String.IsNullOrEmpty(satArr[i]))
                    {
                        continue;
                    }

                    MatchCollection matches = Regex.Matches(satArr[i], pattern);

                    // 判断短波还是卫星
                    if (matches.Count > 0)
                    {
                        // 短波匹配
                        QsoList.Add(GenerateHFAdif(satArr[i]));
                    }
                    else
                    {
                        // 卫星匹配
                        QsoList.Add(GenerateAdif(satArr[i]));
                    }
                }

                // 此时多个QSO完成

                // 结算现场
                // 如果全局QSO数量比1大 说明是多个QSO
                if (QsoList.Count == 1)
                {
                    tbox_outputBox.Text = QsoList[0].qsoCallsigns;
                }
                else
                {
                    foreach (var qso in QsoList)
                    {
                        tbox_outputBox.Text += qso.GetInfo();
                        tbox_outputBox.Text += "\n";
                    }

                    box_SateliteName.Text = "X";
                    box_freq.Text = "X";
                }

                if (g.lang != "简体中文")
                {
                    Sunny.UI.UINotifierHelper.ShowNotifier("Please note this version! The time will be calculated as positive or negative and will no longer be reduced by default. For example, please use '-8' hours for China to UTC conversion!!", 0, "⭐SAT QSO", false, 1500, null) ;

                }
                else
                {

                    Sunny.UI.UINotifierHelper.ShowNotifier("该版本请注意！时间将会按照正负计算，不再默认减少，如：中国转UTC请使用‘-8’小时！！", 0, "⭐SAT QSO", false, 1500, null);
                }

            }
        }

        // 准备要传递给Python脚本的输入字符串
        private void CallAI(string inputString)
        {
            // 设置Python脚本的路径
            string pythonScriptPath = @"C:\Users\Administrator\Desktop\zp.py";

            // 创建一个ProcessStartInfo对象，设置启动信息
            ProcessStartInfo psi = new ProcessStartInfo
            {
                FileName = "python.exe",  // 指定Python解释器的可执行文件路径
                Arguments = pythonScriptPath,  // 指定要执行的Python脚本路径
                RedirectStandardInput = true,  // 重定向标准输入
                RedirectStandardOutput = true,  // 重定向标准输出
                UseShellExecute = false,       // 不使用操作系统外壳程序启动进程
                CreateNoWindow = true          // 不创建窗口
            };

            // 创建一个Process对象，设置启动信息
            using (Process process = new Process { StartInfo = psi })
            {
                // 启动进程
                process.Start();

                // 将输入字符串写入标准输入流
                StreamWriter sw = process.StandardInput;
                sw.WriteLine(inputString);
                sw.Close();  // 关闭输入流，表示输入结束

                // 读取标准输出
                string result = process.StandardOutput.ReadToEnd();

                // 等待进程结束
                process.WaitForExit();

                // 输出Python脚本的执行结果
                tbox_outputBox.Text = "";
                tbox_outputBox.Text += ("Python脚本执行结果：");
                tbox_outputBox.Text += (result);
            }
        }

        static double[] ParseNumbers(string input)
        {
            double[] numbers = new double[2];

            // 使用正则表达式提取数字
            MatchCollection matches = Regex.Matches(input, @"(\d+\.\d+)");

            if (matches.Count >= 2)
            {
                // 将匹配到的字符串转换为double并存储在数组中
                numbers[0] = double.Parse(matches[0].Value);
                numbers[1] = double.Parse(matches[1].Value);
            }
            else
            {
                // 处理无法从输入字符串中提取两个数字的情况
                Console.WriteLine("错误: 无法从输入字符串中提取两个数字。");
            }

            return numbers;
        }

        private void btn_outputADIF_Click(object sender, EventArgs e)
        {
            // 校验合法性
            if (box_SateliteName.Text != "" && box_qsoTime.Text != "" && tbox_outputBox.Text != "")
            {
                RWini.SetPath("config.ini");

                string up_lotw = RWini.ReadValue("upload", "lotw_quiet");
                string up_eqsl = RWini.ReadValue("upload", "eqsl_quiet");
                string up_qrz = RWini.ReadValue("upload", "qrz_quiet");

                bool lotw_quiet = up_lotw.ToLower() == "true";
                bool eqsl_quiet = up_eqsl.ToLower() == "true";
                bool qrz_quiet = up_eqsl.ToLower() == "true";


                bool ban_lotw_enable = RWini.ReadValue("switch", "ban_lotw").ToLower() == "true";
                bool ban_eqsl_enable = RWini.ReadValue("switch", "ban_eqsl").ToLower() == "true";
                bool ban_qrz_enable = RWini.ReadValue("switch", "ban_qrz").ToLower() == "true";

                StringBuilder adifData = new StringBuilder();

                // 添加ADIF头部信息
                adifData.AppendLine("<ADIF_VERS:3>2.2");
                adifData.AppendLine("<CREATED_TIMESTAMP:15>" + DateTime.UtcNow.ToString("yyyyMMdd HHmmss"));
                adifData.AppendLine("<PROGRAMID:7>SAT_QSO");
                adifData.AppendLine("<PROGRAMVERSION:5>2.4.4");
                adifData.AppendLine("<EOH>");
                adifData.AppendLine("");

                for (int i = 0; i < QsoList.Count; i++)
                {
                    if (box_SateliteName.Text != "" && box_qsoTime.Text != "" && tbox_outputBox.Text != "")
                    {
                        // 如果匹配短波频率 那么就添加 
                        if (Regex.IsMatch(QsoList[i].freq, @"\b\d{5,6}\b"))
                        {
                            string[] calls = QsoList[i].qsoCallsigns.Split(new[] { ' ' });
                            string[] QsoDateTime = QsoList[i].qsotime.Split(new[] { ' ' });
                            // 使用Replace方法去除换行符
                            QsoDateTime[1] = QsoDateTime[1].Replace("\n", "00");
                            string freq = QsoList[i].freq; float.TryParse(freq, out float freqF); freq = (freqF / 1000).ToString();
                            string band = QsoList[i].band;
                            string mode = QsoList[i].mode;
                            string comment = QsoList[i].comment;
                            StringBuilder temps = GenerateAdifFile(calls, band, mode, QsoDateTime[0], QsoDateTime[1], freq, "NOSAT", "NOSAT", band, freq, comment);
                            adifData.Append(temps.ToString());
                        }
                        else
                        {
                            //string[] calls = tbox_outputBox.Text.Split(new[] { ' ' });
                            //string[] QsoDateTime = box_qsoTime.Text.Split(new[] { ' ' });

                            string satName = QsoList[i].satelitename;

                            string[] calls = QsoList[i].qsoCallsigns.Split(new[] { ' ' });
                            string[] QsoDateTime = QsoList[i].qsotime.Split(new[] { ' ' });

                            // 使用Replace方法去除换行符
                            QsoDateTime[1] = QsoDateTime[1].Replace("\n", "00");
                            //string sateFreq = getFreq(box_SateliteName.Text);
                            string sateFreq = getFreq(QsoList[i].satelitename);
                            double[] freqs = ParseNumbers(sateFreq);

                            string brandRx = "2M"; //接收波段
                            if (freqs[1].ToString().StartsWith("4"))
                            {
                                brandRx = "70CM";
                            }

                            string baud = "2M";
                            if (freqs[0].ToString().StartsWith("4"))
                            {
                                baud = "70CM";

                            }

                            string mode = "FM";

                            if (satName == "IO-117")
                            {
                                mode = "PKT"; //GreenCube
                            }

                            string returnedString = "";
                            if (satName == "RS-44")
                            {
                                FmConfirmInfo fmConfirmInfo = new FmConfirmInfo();
                                if (fmConfirmInfo.ShowDialog() == DialogResult.OK)
                                {
                                    returnedString = fmConfirmInfo.ReturnedModeString;
                                }

                                if (returnedString == "")
                                {
                                    return; //直接停
                                }
                                mode = returnedString;
                            }

                            // 拿到信息
                            StringBuilder temps = GenerateAdifFile(calls, baud, mode, QsoDateTime[0], QsoDateTime[1], freqs[0].ToString(), "SAT", satName, brandRx, freqs[1].ToString());
                            adifData.Append(temps.ToString());
                        }
                     
                    }
                }

                // 保存ADIF文件
                string backLocation = SaveAdifToFile(adifData.ToString());

                // 开启后台委托模式
                this.BeginInvoke((EventHandler)(delegate
                {
                    if (backLocation != "")
                    {
                        // 除非没有禁用lotw
                        if (!ban_lotw_enable)
                        {
                            // 静默模式lotw
                            if (lotw_quiet)
                            {
                                Lotw_upload(backLocation, lotw_quiet);
                            }
                            else
                            {
                                // 提示保存成功
                                if (Sunny.UI.UIMessageBox.ShowAsk(LangReplace("文件保存成功，你想直接上传它到lotw吗？\n感谢BI3AQ提出的想法。", "saveok"), false) == true)
                                {
                                    Lotw_upload(backLocation, lotw_quiet);
                                }
                            }
                        }

                        if (!ban_eqsl_enable)
                        {
                            if (eqsl_quiet)
                            {
                                Eqsl_upload(backLocation, eqsl_quiet);
                            }
                            else
                            {
                                // 询问EQSL  不填就不问
                                if (tbox_eqslpwd.Text != "" && tbox_eqslAcc.Text != "" && Sunny.UI.UIMessageBox.ShowAsk(LangReplace("你想上传它到EQSL吗？\n", "uploadEqsl"), false) == true)
                                {

                                    Eqsl_upload(backLocation, eqsl_quiet);
                                }
                            }
                        }

                        if (ban_qrz_enable)
                        {
                            // 询问QRZ  不填就不问
                            if (qrz_quiet || (tbox_qrzpwd.Text != "" && tbox_qrzAcc.Text != "" && Sunny.UI.UIMessageBox.ShowAsk(LangReplace("你想上传它到QRZ.COM吗？\n", "uploadQRZ"), false) == true))
                            {
                                Sunny.UI.UIMessageTip.ShowOk(LangReplace("正在处理中，请稍等。。。", "processing"), 8000, false);
                                // 自动上传到QRZ
                                uploadAdifToQRZ(tbox_qrzAcc.Text, tbox_qrzpwd.Text, backLocation);
                            }
                        }
                        
                    }
                }));

            }
            else
            {
                return;
            }
        }


        private void Eqsl_upload(string backLocation,bool quiet)
        {
            int count = 0; string responseString = "";
            while (count <= 3)
            {
                // 自动上传到EQSL
                responseString = UploadFile(CONFIRM_EQSL_URL, backLocation, tbox_eqslAcc.Text, tbox_eqslpwd.Text);
                count++;
                if (responseString != "")
                {
                    break;
                }
            }

            if (quiet)
            {
                UINotifierHelper.ShowNotifier("EQSL OK!", UINotifierType.OK, "⭐EQSL Result", false, 2500, null);
            }
            else
            {
                MessageBox.Show(LangReplace("尝试上传次数：", "uploadTime") + count + LangReplace("\n已为您自动上传到EQSL，请查看结果：\n", "uploadEqslResult") + responseString);
            }

        }
        private void Lotw_upload(string backLocation,bool quiet)
        {
            if (tbox_tqsllocation.Text.Length == 0 || tbox_stationName.Text.Length == 0) {
                Sunny.UI.UIMessageBox.ShowError(LangReplace("请填入对应的台站名称~！在TQSL的台站位置-> 编辑台站位置 -> 下一步 -> 复制编辑你的台站位置", "fillStationName"), false);
                Sunny.UI.UIMessageTip.ShowOk(LangReplace("没有TQSL路径，需要选择TQSL路径，你需要找到TQSL路径并选择EXE文件。", "noTQSLPath"), 5000, false);
                return;
            }
            byte[] bytes = Encoding.Default.GetBytes(backLocation); // 使用正确的编码，比如UTF-8、GBK等
            string decodedPath = Encoding.Default.GetString(bytes); // 使用相同的编码解码

            string cmd = @"tqsl -q -l """ + tbox_stationName.Text + @""" -p ""Insecure"" -a all -u -d """ + backLocation + @"""  2>temp.txt"; // 执行CMD

            string directory = Path.GetDirectoryName(tbox_tqsllocation.Text);
            string workingDirectory = directory; // 指定目录

            // MessageBox.Show(cmd);

            ExecuteCommand(cmd, workingDirectory); // 执行CMD命令

            string filePath = Path.Combine(workingDirectory, "temp.txt");
            string fileContent = ReadFile(filePath, Encoding.GetEncoding("GB2312"));
            fileContent = GetLastNCharacters(fileContent, 200);
            if (quiet)
            {
                UINotifierHelper.ShowNotifier("LOTW OK!", UINotifierType.OK, "⭐LOTW Result", false, 2500, null);
            }
            else
            {
                MessageBox.Show(LangReplace("可以关闭检查你的lotw日志了：\n ...", "checklotw") + fileContent);
            }
            // 
        }

        static string ExecuteCommand(string command, string workingDirectory)
        {
            ProcessStartInfo startInfo = new ProcessStartInfo();
            startInfo.FileName = "cmd.exe";
            startInfo.WorkingDirectory = workingDirectory;
            startInfo.Arguments = "/C \"" + command + "\""; // 使用双引号将路径和命令括起来
            startInfo.RedirectStandardOutput = true; // 将输出重定向到程序中
            startInfo.UseShellExecute = false; // 关闭Shell的使用
            startInfo.StandardOutputEncoding = Encoding.Default;

            Process process = new Process();
            process.StartInfo = startInfo;
            process.Start();

            process.WaitForExit();

            string output = process.StandardOutput.ReadToEnd(); // 读取输出结果
            return output;
        }


        static string ReadFile(string filePath, Encoding encoding)
        {
            if (File.Exists(filePath))
            {
                using (StreamReader reader = new StreamReader(filePath, encoding))
                {
                    string fileContent = reader.ReadToEnd();
                    return fileContent;
                }
            }
            else
            {
                return "文件不存在。";
            }
        }

        public StringBuilder GenerateAdifFile(string[] calls, string band, string mode, string qsoDate, string timeOn, string freq, string propMode, string satName, string brandRx, string freqsRx,string comment="")
        {
            // 使用StringBuilder来构建ADIF字符串，提高性能
            StringBuilder adifBuilder = new StringBuilder();

            foreach (var call in calls)
            {
                if (call.Length != 0 && mode != null && band != null )
                {
                    // 添加QSO记录
                    adifBuilder.AppendLine("<CALL:" + call.Length + ">" + call);
                    adifBuilder.AppendLine("   <BAND:" + band.Length + ">" + band);
                    adifBuilder.AppendLine("   <MODE:" + mode.Length + ">" + mode);
                    adifBuilder.AppendLine("   <QSO_DATE:" + qsoDate.Length + ">" + qsoDate);
                    if (CBox_TimeMove.Checked)
                    {
                        int.TryParse(timeOn, out int timeOnNum);
                        timeOnNum += 1;
                        // 处理秒数超过60的情况
                        int seconds = timeOnNum % 100;
                        if (seconds >= 60)
                        {
                            timeOnNum += 40; // 60秒进位到分钟 (100-60=40)
                        }
                        timeOn = timeOnNum.ToString("D6");
                    }
                    adifBuilder.AppendLine("   <TIME_ON:" + timeOn.Length + ">" + timeOn);
                    if (freq != null)
                    {
                        adifBuilder.AppendLine("   <FREQ:" + freq.Length + ">" + freq);
                    }

                    adifBuilder.AppendLine("   <BAND_RX:" + brandRx.Length + ">" + brandRx);
                    adifBuilder.AppendLine("   <FREQ_RX:" + freqsRx.Length + ">" + freqsRx);

                    if (!string.IsNullOrEmpty(propMode) && propMode != "NOSAT")
                    {
                        adifBuilder.AppendLine("   <PROP_MODE:" + propMode.Length + ">" + propMode);
                    }
                    if (!string.IsNullOrEmpty(satName) && satName!= "NOSAT")
                    {
                        adifBuilder.AppendLine("   <SAT_NAME:" + satName.Length + ">" + satName);
                    }
                    if (!String.IsNullOrEmpty(comment)) {
                        adifBuilder.AppendLine($"   <COMMENT:{comment.Length+1}>{comment}");
                    }
                    adifBuilder.AppendLine("<EOR>");
                }
            }

            return adifBuilder;
        }

        public static string SaveAdifToFile(string adifData)
        {
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.Filter = "ADIF Files|*.adi|All Files|*.*";
            saveFileDialog.Title = "Save ADIF File";
            saveFileDialog.FileName = "QSO_Log.adi";

            if (saveFileDialog.ShowDialog() == DialogResult.OK)
            {
                // 获取用户选择的文件路径
                string filePath = saveFileDialog.FileName;

                // 将ADIF数据写入文件
                File.WriteAllText(filePath, adifData);

                return filePath;
            }

            return "";
        }

        private string CalcuTimeDiff(string inputTime)
        {
            if (CBox_Low8Hour.Checked)
            {
                // 将输入字符串解析为DateTime对象
                DateTime localTime = DateTime.ParseExact(inputTime, "yyyyMMdd HHmmss", null);

                // 获取本机的时区信息
                TimeZoneInfo localTimeZone = TimeZoneInfo.Local;

                // 根据用户选择往前或往后推时间
                DateTime gmtPlus8Time = TimeZoneInfo.ConvertTime(localTime, localTimeZone);

                // 往前推8小时
                DateTime utcTime = gmtPlus8Time.AddHours(-iud_timediff.Value);

                // 将UTC时间格式化为字符串，保持原格式
                string utcTimeString = utcTime.ToString("yyyyMMdd HHmmss");

                // 输出结果
                Console.WriteLine(utcTimeString);

                inputTime = utcTimeString;
            }
            else
            {
                // 将输入字符串解析为DateTime对象
                DateTime localTime = DateTime.ParseExact(inputTime, "yyyyMMdd HHmmss", null);

                // 获取本机的时区信息
                TimeZoneInfo localTimeZone = TimeZoneInfo.Local;

                // 根据用户选择往前或往后推时间
                DateTime gmtPlus8Time = TimeZoneInfo.ConvertTime(localTime, localTimeZone);

                // 往前推8小时
                DateTime utcTime = gmtPlus8Time.AddHours(+iud_timediff.Value);

                // 将UTC时间格式化为字符串，保持原格式
                string utcTimeString = utcTime.ToString("yyyyMMdd HHmmss");

                // 输出结果
                Console.WriteLine(utcTimeString);

                inputTime = utcTimeString;
            }

            return inputTime;
        }

        private void CBox_Low8Hour_CheckedChanged(object sender, EventArgs e)
        {

            Btn_analysis_Click(null, null);


           /* if (box_qsoTime.Text != "")
            {
                if (CBox_Low8Hour.Checked)
                {
                    // 将输入字符串解析为DateTime对象
                    DateTime localTime = DateTime.ParseExact(box_qsoTime.Text, "yyyyMMdd HHmmss", null);

                    // 获取本机的时区信息
                    TimeZoneInfo localTimeZone = TimeZoneInfo.Local;

                    // 根据用户选择往前或往后推时间
                    DateTime gmtPlus8Time = TimeZoneInfo.ConvertTime(localTime, localTimeZone);

                    // 往前推8小时
                    DateTime utcTime = gmtPlus8Time.AddHours(iud_timediff.Value);

                    // 将UTC时间格式化为字符串，保持原格式
                    string utcTimeString = utcTime.ToString("yyyyMMdd HHmmss");

                    // 输出结果
                    Console.WriteLine(utcTimeString);

                    box_qsoTime.Text = utcTimeString;
                }
                else
                {
                    // 将输入字符串解析为DateTime对象
                    DateTime localTime = DateTime.ParseExact(box_qsoTime.Text, "yyyyMMdd HHmmss", null);

                    // 获取本机的时区信息
                    TimeZoneInfo localTimeZone = TimeZoneInfo.Local;

                    // 根据用户选择往前或往后推时间
                    DateTime gmtPlus8Time = TimeZoneInfo.ConvertTime(localTime, localTimeZone);

                    // 往前推8小时
                    DateTime utcTime = gmtPlus8Time.AddHours(-iud_timediff.Value);

                    // 将UTC时间格式化为字符串，保持原格式
                    string utcTimeString = utcTime.ToString("yyyyMMdd HHmmss");

                    // 输出结果
                    Console.WriteLine(utcTimeString);

                    box_qsoTime.Text = utcTimeString;
                }

            }*/

            if (CBox_Low8Hour.Checked)
            {
                RWini.WriteValue("timediff", "checked", "true");
            }
            else
            {
                RWini.WriteValue("timediff", "checked", "false");
            }

        }
        static string GetClipboardText()
        {
            if (Clipboard.ContainsText())
            {
                return Clipboard.GetText();
            }

            return null;
        }

        private void btn_copyform_Click(object sender, EventArgs e)
        {
            // 读取剪贴板中的文本
            string clipboardText = GetClipboardText();

            if (!string.IsNullOrEmpty(clipboardText))
            {
                Console.WriteLine("剪贴板中的文本内容：");
                Console.WriteLine(clipboardText);
                tbox_inputbox.Text = clipboardText;
            }
        }

        public void CopyTextToClipboard(UIRichTextBox textBox)
        {
            // 检查TextBox是否有文本
            if (!string.IsNullOrEmpty(textBox.Text))
            {
                // 将TextBox的文本复制到剪贴板
                Clipboard.SetText(textBox.Text);
            }
        }

        private void btn_clear_Click(object sender, EventArgs e)
        {
            box_qsoTime.Clear();
            box_SateliteName.Clear();
            box_freq.Clear();
            tbox_inputbox.Text = "";
            tbox_outputBox.Text = "";

        }

        private List<string> ReadStationName() {

            string filePath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\TrustedQSL\\station_data";

            // 检查路径是否存在
            if (!Directory.Exists(Path.GetDirectoryName(filePath)))
            {
                List<string> ls = new List<string>
                {
                    "No station data"
                };
                return ls;
            }

            string fileContents = string.Empty;
            using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
            {
                using (StreamReader reader = new StreamReader(fs))
                {
                    fileContents = reader.ReadToEnd();
                }
            }
            List<string> stationName = ReadXmlData(fileContents);
            return stationName;
        }
        private void Form1_Load(object sender, EventArgs e)
        {
        
            Sunny.UI.UIMessageTip.ShowOk(LangReplace("先输入QSO信息并点击分析按钮，然后再导出ADIF文件！", "loadTip"), 5000, false);
            RWini.SetPath("config.ini");
            tbox_tqsllocation.Text = RWini.ReadValue("tqsl", "tqsl_Location");

           
            tbox_stationName.DataSource = ReadStationName();

            tbox_stationName.Text = RWini.ReadValue("tqsl", "tqsl_StationName"); tbox_stationName.ForeColor = Color.Black; btn_ConfirmstationName.Enabled = false;


            tbox_eqslAcc.Text = RWini.ReadValue("eqsl", "account");
            string pdwrsa = RWini.ReadValue("eqsl", "password");

            //var keys = GetHardSystemSerialNumber();
            var keys = Environment.UserName;

            RSASecurity.RSAKey = keys;
            tbox_eqslpwd.Text = RSASecurity.DecryptRSA(pdwrsa);

            btn_ConfirmEQSLACCPWD.Enabled = false;


            //qrz Prefill
            tbox_qrzAcc.Text = RWini.ReadValue("sync", "callsign");
            string pdwrsa_qrz = RWini.ReadValue("sync", "qrz_pwd");

            //CNtoPinYin
            cnToPY_checkBox.Checked = RWini.ReadValue("CNtoPinYin", "checked") == "true";

            //var keys = GetHardSystemSerialNumber();
            var keys_qrz = Environment.UserName;

            RSASecurity.RSAKey = keys_qrz;
            tbox_qrzpwd.Text = RSASecurity.DecryptRSA(pdwrsa_qrz);

            btn_ConfirmQRZACCPWD.Enabled = false;


            string valueStr = RWini.ReadValue("timediff", "diff");
            int.TryParse(valueStr, out int timediffvlue);
            iud_timediff.Value = timediffvlue; // 初始化时间差

            string checkstatus = RWini.ReadValue("timediff", "checked");
            if (checkstatus == "true")
            {
                CBox_Low8Hour.Checked = true;
            }

            RWini.SetPath("config.ini");
            string timeMoveStatus = RWini.ReadValue("timemove", "checked");
            if (timeMoveStatus == "true")
            {
                CBox_TimeMove.Checked = true;
            }

            tbox_stationName.Watermark = LangReplace("请输入TQSL中的完整台站名称", "stationName");
            tbox_eqslAcc.Watermark = LangReplace("EQSL用户名", "eqslAcc");
            tbox_eqslpwd.Watermark = LangReplace("EQSL密码", "eqslpwd");

            this.Text = LangReplace("卫星QSO解析，作者：BG5BTK，翻译：BH6BEZ", "title");

            tbox_stationName.Focus();

        }
        static List<string> ReadXmlData(string xmlContent)
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(xmlContent);
            List<string> nameList = new List<string>();
            XmlNodeList stationDataList = xmlDoc.GetElementsByTagName("StationData");
            foreach (XmlNode stationDataNode in stationDataList)
            {
                string name = stationDataNode.Attributes["name"].Value;
                string call = stationDataNode.SelectSingleNode("CALL").InnerText;

                Console.WriteLine($"Name: {name}");
                Console.WriteLine($"CALL: {call}");
                Console.WriteLine();


                nameList.Add(name);
            }

            // 输出nameList中的每个名称
            foreach (string name in nameList)
            {
                Console.WriteLine($"Name: {name}");
            }

            return nameList;
        }
        private void btn_confirm_Click(object sender, EventArgs e)
        {
            if (tbox_tqsllocation.Text == "")
            {
                Sunny.UI.UIMessageTip.ShowOk(LangReplace("没有TQSL路径，需要选择TQSL路径，你需要找到TQSL路径并选择EXE文件。", "noTQSLPath"), 5000, false);
                string location = ShowFileSelector();
                if (location != "")
                {
                    RWini.SetPath("config.ini");
                    tbox_tqsllocation.Text = location;
                    RWini.WriteValue("tqsl", "tqsl_Location", location);
                }
                return;
            }

            if (tbox_stationName.Text != "" && tbox_tqsllocation.Text != "") 
            {
                Sunny.UI.UIMessageTip.ShowOk(LangReplace("选择你要上传的ADIF文件", "selectADIF"), 2000, false);
                string location = ShowFileSelector();
                if (location != "" && Sunny.UI.UIMessageBox.ShowAsk(LangReplace("确定要上传嘛？\n（此处感谢BD8DFV帮忙排查出Bug）", "sureUpload"), false)) 
                {
                    string cmd = @"tqsl -q -l """ + tbox_stationName.Text + @""" -p ""Insecure"" -a all -u -d """ + location + @"""  2>temp.txt"; // 执行的CMD命令

                    string directory = Path.GetDirectoryName(tbox_tqsllocation.Text);
                    string workingDirectory = directory; // 指定目录

                    // MessageBox.Show(cmd);

                    ExecuteCommand(cmd, workingDirectory); // 执行CMD命令

                    Thread.Sleep(3000);

                    string filePath = Path.Combine(workingDirectory, "temp.txt");
                    string fileContent = ReadFile(filePath, Encoding.GetEncoding("GB2312"));
                    fileContent = GetLastNCharacters(fileContent, 200);
                    MessageBox.Show(LangReplace("可以关闭检查你的lotw日志了：", "uploadFinish") + " \n ..." + fileContent);
                }
            }
            else
            {
                Sunny.UI.UIMessageBox.ShowError(LangReplace("请填入对应的台站名称~！在TQSL的台站位置-> 编辑台站位置 -> 下一步 -> 复制编辑你的台站位置", "fillStationName"), false);
            }

        }

        static string GetLastNCharacters(string str, int n)
        {
            if (str.Length <= n)
                return str;
            else
                return str.Substring(str.Length - n);
        }

        public string ShowFileSelector()
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.FileName = "QSO_Log.adi";
            if (dialog.ShowDialog() == DialogResult.OK)
            {
                return dialog.FileName;
            }
            else
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// 打开URL
        /// </summary>
        /// <param name="url"></param>
        static void OpenWebPage(string url)
        {
            try
            {
                // 使用默认的Web浏览器打开URL
                Process.Start(new ProcessStartInfo
                {
                    FileName = url,
                    UseShellExecute = true
                });
            }
            catch (Exception ex)
            {
                Console.WriteLine($"发生异常: {ex.Message}");
            }
        }

        private void sbtn_how2use_Click(object sender, EventArgs e)
        {
            if (Sunny.UI.UIMessageBox.ShowAsk(LangReplace("即将打开说明书PDF文件，确定吗？", "openPDF"), false) == true)
            {
                try
                {
                    // 获取当前执行程序的目录
                    string currentDirectory = AppDomain.CurrentDomain.BaseDirectory;

                    // 拼接PDF文件的完整路径
                    string pdfFilePath = System.IO.Path.Combine(currentDirectory, "批量QSO生成ADIF工具使用说明书.pdf");

                    // 检查文件是否存在
                    if (System.IO.File.Exists(pdfFilePath))
                    {
                        // 使用默认的PDF阅读器打开文件
                        Process.Start(pdfFilePath);
                    }
                    else
                    {
                        Console.WriteLine("指定的PDF文件不存在： " + pdfFilePath);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("打开PDF文件时出现错误： " + ex.Message);
                }
            }
            
        }

        private void Sbtn_author_Click(object sender, EventArgs e)
        {
            if (Sunny.UI.UIMessageBox.ShowAsk(LangReplace("即将打开浏览器，您确定访问BG5BTK的QRZ主页吗", "qrzPage"), false) == true)
            {
                Sunny.UI.UIMessageTip.ShowOk("Mabuhey~！！！", 2000, true);
                string url = "https://www.qrz.com/db/BG5BTK";

                // 打开默认的Web浏览器并访问指定的URL
                OpenWebPage(url);
            }
        }

        private void btn_changeTqslLocation_Click(object sender, EventArgs e)
        {
            Sunny.UI.UIMessageBox.ShowInfo(LangReplace("你需要找到TQSL路径并选择EXE文件。\n尝试查找路径：D:\\Program Files (x86)\\TrustedQSL\n 或者：C:\\Program Files (x86)\\TrustedQSL\n 【请注意】：不推荐您使用C盘安装TQSL，因为权限问题可能会没有返回结果，您可以备份后卸载重装到D盘为佳", "changetqslPath"), false);
            string location = ShowFileSelector();
            if (location != "")
            {
                RWini.SetPath("config.ini");
                tbox_tqsllocation.Text = location;
                RWini.WriteValue("tqsl", "tqsl_Location", location);

                tbox_stationName.DataSource = ReadStationName();
            }
        }

        private void tbox_stationName_TextChanged(object sender, EventArgs e)
        {
            tbox_stationName.ForeColor = Color.Red;
            btn_ConfirmstationName.Style = UIStyle.Red;
            btn_ConfirmstationName.Enabled = true;
        }

        private void btn_ConfirmstationName_Click(object sender, EventArgs e)
        {
            tbox_stationName.ForeColor = Color.Black;
            btn_ConfirmstationName.Enabled = false;
            RWini.SetPath("config.ini");
            RWini.WriteValue("tqsl", "tqsl_StationName", tbox_stationName.Text);
        }

        private void tbox_inputbox_MouseHover(object sender, EventArgs e)
        {
            Sunny.UI.UIMessageTip.ShowWarning(LangReplace("输入格式：\n时间 卫星名称 呼号（呼号可以一次性输入多条，空格隔开即可）\n如有多个QSO请用*号隔开", "inputformat"), 5000, false);
        }

        private void btn_openSourcePage_Click(object sender, EventArgs e)
        {
            if (Sunny.UI.UIMessageBox.ShowAsk(LangReplace("即将访问项目页面，打开浏览器？", "opengit"), false) == true)
            {
                string url = "https://gitee.com/yuzhenwu/x-qsl-amateur-radio-adif-tool";

                // 打开默认的Web浏览器并访问指定的URL
                OpenWebPage(url);
            }
        }


        public static string GetHardSystemSerialNumber()
        {
            string result = "";
            ManagementClass mc = new ManagementClass("Win32_DiskDrive");
            ManagementObjectCollection moc = mc.GetInstances();
            foreach (ManagementObject mo in moc)
            {
                if (mo["InterfaceType"].ToString() == "IDE" || mo["InterfaceType"].ToString() == "SCSI")
                {
                    result = mo["SerialNumber"].ToString().Trim();
                    break;
                }
            }
            return result;
        }

        private void lab_eqslAcc_Click(object sender, EventArgs e)
        {
            //string url = "https://www.eQSL.cc/qslcard/ImportADIF.cfm";
            //string filePath = "E:\\DeskTOP-E\\QSO_Log.adi";

            //await UploadToEQSL(url, tbox_eqslAcc.Text, tbox_eqslpwd.Text, filePath);

            //string filePath = @"E:\DeskTOP-E\QSO_Log.adi"; // 替换为你的ADIF文件路径
            //string eqslUser = tbox_eqslAcc.Text;
            //string eqslPassword = tbox_eqslpwd.Text;

            // UploadFile(url, backLocation, eqslUser, eqslPassword);

        }
        static string UploadFile(string url, string filePath, string eqslUser, string eqslPassword)
        {
            using (WebClient client = new WebClient())
            {
                // 设置请求头，指定Content-Type为multipart/form-data
                client.Headers.Add("Content-Type", "multipart/form-data; boundary=" + "---------------------------" + DateTime.Now.Ticks.ToString("x"));

                // 构建表单数据
                StringBuilder sb = new StringBuilder();
                sb.AppendLine("-----------------------------" + DateTime.Now.Ticks.ToString("x"));
                sb.AppendLine("Content-Disposition: form-data; name=\"EQSL_USER\"");
                sb.AppendLine();
                sb.AppendLine(eqslUser);

                sb.AppendLine("-----------------------------" + DateTime.Now.Ticks.ToString("x"));
                sb.AppendLine("Content-Disposition: form-data; name=\"EQSL_PSWD\"");
                sb.AppendLine();
                sb.AppendLine(eqslPassword);

                sb.AppendLine("-----------------------------" + DateTime.Now.Ticks.ToString("x"));
                sb.AppendLine($"Content-Disposition: form-data; name=\"Filename\"; filename=\"{Path.GetFileName(filePath)}\"");
                sb.AppendLine("Content-Type: application/octet-stream");
                sb.AppendLine();

                string header = sb.ToString();
                byte[] headerBytes = Encoding.UTF8.GetBytes(header);
                byte[] footerBytes = Encoding.UTF8.GetBytes(Environment.NewLine + "-----------------------------" + DateTime.Now.Ticks.ToString("x") + "--" + Environment.NewLine);

                // 读取文件内容
                byte[] fileBytes = File.ReadAllBytes(filePath);

                // 合并请求数据
                byte[] formData = new byte[headerBytes.Length + fileBytes.Length + footerBytes.Length];
                Buffer.BlockCopy(headerBytes, 0, formData, 0, headerBytes.Length);
                Buffer.BlockCopy(fileBytes, 0, formData, headerBytes.Length, fileBytes.Length);
                Buffer.BlockCopy(footerBytes, 0, formData, headerBytes.Length + fileBytes.Length, footerBytes.Length);

                // 上传文件
                byte[] responseBytes;
                try
                {
                    responseBytes = client.UploadData(url, "POST", formData);
                }
                catch (WebException ex)
                {
                    responseBytes = Encoding.UTF8.GetBytes(ex.Message);
                }

                // 处理响应
                string responseString = Encoding.UTF8.GetString(responseBytes);

                return responseString;
            }
        }

        static string ParseHtml(string htmlCode)
        {
            // Define regular expressions to extract relevant information
            Regex informationRegex = new Regex(@"Information: Received (\d+) bytes<BR>");
            Regex resultRegex = new Regex(@"Result: (\d+) out of (\d+) records added<BR>");
            Regex qsoRegex = new Regex(@"Information: From: (.+?) To: (.+?) Date: (\d{8}) Time: (\d{4}) Band: (.+?) Mode: (.+?) RST: (.+?)  PropMode: (.+?) SatName: (.+?)<BR>");

            // Match the regular expressions in the HTML code
            Match informationMatch = informationRegex.Match(htmlCode);
            Match resultMatch = resultRegex.Match(htmlCode);
            Match qsoMatch = qsoRegex.Match(htmlCode);

            // Extract and build the information string
            string parsedInformation = "";

            if (informationMatch.Success)
            {
                string receivedBytes = informationMatch.Groups[1].Value;
                parsedInformation += $"Received Bytes: {receivedBytes}\n";
            }

            if (resultMatch.Success)
            {
                string recordsAdded = resultMatch.Groups[1].Value;
                string totalRecords = resultMatch.Groups[2].Value;
                parsedInformation += $"Records Added: {recordsAdded} out of {totalRecords}\n";
            }

            if (qsoMatch.Success)
            {
                string from = qsoMatch.Groups[1].Value;
                string to = qsoMatch.Groups[2].Value;
                string date = qsoMatch.Groups[3].Value;
                string time = qsoMatch.Groups[4].Value;
                string band = qsoMatch.Groups[5].Value;
                string mode = qsoMatch.Groups[6].Value;
                string rst = qsoMatch.Groups[7].Value;
                string propMode = qsoMatch.Groups[8].Value;
                string satName = qsoMatch.Groups[9].Value;

                parsedInformation += $"QSO Information: From: {from}, To: {to}, Date: {date}, Time: {time}, Band: {band}, Mode: {mode}, RST: {rst}, PropMode: {propMode}, SatName: {satName}\n";
            }

            // Return the parsed information string
            return parsedInformation;
        }

        private void btn_ConfirmEQSLACCPWD_Click(object sender, EventArgs e)
        {
            if (tbox_eqslAcc.Text != "" && tbox_eqslpwd.Text != "")
            {
                RWini.SetPath("config.ini");

                RWini.WriteValue("eqsl", "account", tbox_eqslAcc.Text);

                // 加密密码
                //var keys = GetHardSystemSerialNumber();
                var keys = Environment.UserName;
                RSASecurity.RSAKey = keys;
                string result = RSASecurity.EncryptRSA(tbox_eqslpwd.Text);
                RWini.WriteValue("eqsl", "password", result);

                Sunny.UI.UIMessageTip.ShowOk(LangReplace("已保存EQSL信息。。", "saved"), 2000, false);


                btn_ConfirmEQSLACCPWD.Enabled = false;
            }
            else
            {
                Sunny.UI.UIMessageTip.ShowError(LangReplace("账户或者密码没写。。", "noAccOrPwd"), 2000, false);
            }
        }

        private void btn_confirm_EQSL_Click(object sender, EventArgs e)
        {
            if (tbox_eqslAcc.Text == "" || tbox_eqslpwd.Text == "")
            {
                Sunny.UI.UIMessageTip.ShowError(LangReplace("请你填写EQSL账户密码", "fillAccAndPwd"), 5000, false);

                return;
            }

            string location = ShowFileSelector();
            if (location != "" && Sunny.UI.UIMessageBox.ShowAsk(LangReplace("确定要上传EQSL嘛？", "sureUploadEqsl"), false))
            {
                int count = 0; string responseString = "";
                while (count <= 3)
                {
                    // 自动上传到EQSL
                    responseString = UploadFile(CONFIRM_EQSL_URL, location, tbox_eqslAcc.Text, tbox_eqslpwd.Text);
                    count++;
                    if (responseString != "")
                    {
                        break;
                    }
                }

                // responseString = ParseHtml(responseString);
                MessageBox.Show(LangReplace("尝试上传次数：", "tryed") + count + "\n"+ LangReplace("已为您自动上传到EQSL，请查看结果", "upEqslResult") +"：\n" + responseString);
            }
        }

        private void tbox_eqslpwd_TextChanged(object sender, EventArgs e)
        {
            btn_ConfirmEQSLACCPWD.Style = UIStyle.Red;
            btn_ConfirmEQSLACCPWD.Enabled = true;
        }

        private void tbox_eqslAcc_TextChanged(object sender, EventArgs e)
        {
            btn_ConfirmEQSLACCPWD.Style = UIStyle.Red;
            btn_ConfirmEQSLACCPWD.Enabled = true;
        }

        private void combox_lang_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (LANG_INIT_STATUS)
            {
                RWini.SetPath("config.ini");
                RWini.WriteValue("lang", "current", combox_lang.Text);

                System.Windows.Forms.Application.Restart();
            }
        }

        private void iud_timediff_ValueChanged(object sender, int value)
        {
            RWini.SetPath("config.ini");
            RWini.WriteValue("timediff", "diff", iud_timediff.Value);

            if (CBox_Low8Hour.Checked)
            {
                RWini.WriteValue("timediff", "checked", "true");
            }
        }

        private void uiLabel1_Click(object sender, EventArgs e)
        {
            if (Sunny.UI.UIMessageBox.ShowAsk(LangReplace("检查最新版本？", "cheVersion"), false) == true)
            {
                string url = "https://gitee.com/yuzhenwu/x-qsl-amateur-radio-adif-tool/releases";

                // 打开默认的Web浏览器并访问指定的URL
                OpenWebPage(url);
            }
        }

        private void lab_version_MouseHover(object sender, EventArgs e)
        {
            lab_version.ForeColor = Color.Red;
        }

        private void lab_version_MouseLeave(object sender, EventArgs e)
        {
            lab_version.ForeColor = Color.Black;
        }

        /// <summary>
        /// 从QRZ同步lotw信息过来
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_qrz_lotw_Click(object sender, EventArgs e)
        {
            // 打开提醒页面
            // 创建并显示模态对话框
            FmQrzSynchronizePage fm = new FmQrzSynchronizePage();
            fm.ShowDialog();
        }

        private void btn_RuleOut_Click(object sender, EventArgs e)
        {
            CreateOrOpenFile("callsigns.ini"); 
        }

        void CreateOrOpenFile(string fileName)
        {
            string filePath = Path.Combine(Directory.GetCurrentDirectory(), fileName);

            if (!File.Exists(filePath))
            {
                using (StreamWriter sw = File.CreateText(filePath))
                {
                    Console.WriteLine("文件不存在，已创建文件: " + filePath);
                }
            }
            else
            {
                Console.WriteLine("文件已存在: " + filePath);
            }

            try
            {
                Process.Start(@fileName);

            }
            catch (Exception ex)
            {
                Console.WriteLine("无法打开文件: " + ex.Message);
                
                Sunny.UI.UIMessageTip.ShowWarning(LangReplace("无法自动打开文件，已帮你手动打开路径，请自行编辑。", "cantopennotepad"));
                try
                {
                    // 使用资源管理器的特定命令
                    Process.Start("explorer.exe", $"/select,\"{filePath}\"");
                }
                catch (Exception exs)
                {
                    Console.WriteLine("Error: " + exs.Message);
                }
            }
        }

        private void sbtn_settings_Click(object sender, EventArgs e)
        {
            FmSettings fmSettings = new FmSettings();
            fmSettings.ShowDialog();
        }

        /// <summary>
        /// 返回波段M
        /// </summary>
        /// <param name="frequencyKHz"></param>
        /// <returns></returns>
        static string GetBand(double frequencyKHz)
        {
            double frequencyHz = frequencyKHz; // 将 kHz 转换为 Hz

            if (frequencyHz >= 420000 && frequencyHz <= 450000)
            {
                return "70CM";
            }
            else if (frequencyHz >= 220000 && frequencyHz <= 225000)
            {
                return "1.25M";
            }
            else if (frequencyHz >= 144000 && frequencyHz <= 148000)
            {
                return "2M";
            }
            else if (frequencyHz >= 70000 && frequencyHz <= 71000)
            {
                return "4M";
            }
            else if (frequencyHz >= 50000 && frequencyHz <= 54000)
            {
                return "6M";
            }
            else if (frequencyHz >= 28000 && frequencyHz <= 29700)
            {
                return "10M";
            }
            else if (frequencyHz >= 24890 && frequencyHz <= 24990)
            {
                return "12M";
            }
            else if (frequencyHz >= 21000 && frequencyHz <= 21450)
            {
                return "15M";
            }
            else if (frequencyHz >= 18068 && frequencyHz <= 18168)
            {
                return "17M";
            }
            else if (frequencyHz >= 14000 && frequencyHz <= 14350)
            {
                return "20M";
            }
            else if (frequencyHz >= 10100 && frequencyHz <= 10150)
            {
                return "30M";
            }
            else if (frequencyHz >= 7000 && frequencyHz <= 7300)
            {
                return "40M";
            }
            else if (frequencyHz >= 5250 && frequencyHz <= 5450)
            {
                return "60M";
            }
            else if (frequencyHz >= 3500 && frequencyHz <= 4000)
            {
                return "80M";
            }
            else if (frequencyHz >= 1800 && frequencyHz <= 2000)
            {
                return "160M";
            }
            else
            {
                return "Unknown band";
            }
        }

        /// <summary>
        /// QRZ用户名密码保存按钮被点击 和lotw->QRZ共享配置：qrz_pwd 和 callsign
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_ConfirmQRZACCPWD_Click(object sender, EventArgs e)
        {
            if (tbox_qrzAcc.Text != "" && tbox_qrzpwd.Text != "")
            {
                RWini.SetPath("config.ini");

                RWini.WriteValue("sync", "callsign", tbox_qrzAcc.Text);

                // 加密密码
                //var keys = GetHardSystemSerialNumber();
                var keys = Environment.UserName;
                RSASecurity.RSAKey = keys;
                string result = RSASecurity.EncryptRSA(tbox_qrzpwd.Text);
                RWini.WriteValue("sync", "qrz_pwd", result);

                Sunny.UI.UIMessageTip.ShowOk(LangReplace("已保存QRZ信息。。", "saved"), 2000, false);


                btn_ConfirmQRZACCPWD.Enabled = false;
            }
            else
            {
                Sunny.UI.UIMessageTip.ShowError(LangReplace("账户或者密码没写。。", "noAccOrPwd"), 2000, false);
            }
        }

        private void tbox_qrzAcc_TextChanged(object sender, EventArgs e)
        {
            btn_ConfirmQRZACCPWD.Enabled = true;

        }

        private void tbox_qrzpwd_TextChanged(object sender, EventArgs e)
        {
            btn_ConfirmQRZACCPWD.Enabled = true;

        }


        private void btn_qrz_adif_Click(object sender, EventArgs e)
        {
            Sunny.UI.UIMessageTip.ShowOk(LangReplace("选择你要上传的ADIF文件", "selectADIF"), 2000, false);
            string location = ShowFileSelector();
            if (location != "" && Sunny.UI.UIMessageBox.ShowAsk(LangReplace("确定要上传嘛？\n", "sureUpload"), false))
            {
                uploadAdifToQRZ(tbox_qrzAcc.Text, tbox_qrzpwd.Text, location);
                Sunny.UI.UIMessageTip.ShowOk(LangReplace("正在处理中，请稍等。。。", "processing"), 8000, false);
            }

        }

        /// <summary>
        /// 上传adif到qrz.com
        /// </summary>
        private void uploadAdifToQRZ(string callsign, string qrz_pwd,string adiPath) {
            if (callsign.Length !=0 && qrz_pwd.Length != 0 && adiPath.Length != 0)
            {
                string qMode = "";
                string filePath = "qrz_auto_import_from_lotw.exe";
                string arguments = $"{callsign} {qrz_pwd} --adif {adiPath}" + qMode; // 设置需要传递的参数

                try
                {
                    ProcessStartInfo startInfo = new ProcessStartInfo();
                    startInfo.FileName = filePath;
                    startInfo.Arguments = arguments;

                    Process.Start(startInfo);
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Error opening file: " + ex.Message);
                }
            }
            else
            {
                Sunny.UI.UIMessageTip.ShowError(LangReplace("账户/密码/路径没写。。", "noAccOrPwdOrPath"), 2000, false);
            }
        }

        /// <summary>
        /// 中文转拼音按钮被点击
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cnToPY_checkBox_CheckedChanged(object sender, EventArgs e)
        {
            Btn_analysis_Click(null, null);

            if (cnToPY_checkBox.Checked)
            {
                RWini.WriteValue("CNtoPinYin", "checked", "true");
            }
            else
            {
                RWini.WriteValue("CNtoPinYin", "checked", "false");
            }
        }

        private void lab_Result_Click(object sender, EventArgs e)
        {
            CopyTextToClipboard(tbox_outputBox);
            Sunny.UI.UIMessageTip.ShowOk("B~T~K~!ヾ(≧▽≦*)o", 1000);
        }

        private void CBox_TimeMove_CheckedChanged(object sender, EventArgs e)
        {
            RWini.SetPath("config.ini");
            if (CBox_TimeMove.Checked)
            {
                RWini.WriteValue("timemove", "checked", "true");
            }
            else
            {
                RWini.WriteValue("timemove", "checked", "false");
            }
        }
    }
}
